import { MotaInterface } from '@/mota';
import ScrollTool from '@/mota/tools/ScrollTool';
import BuildUtils from '@/mota/utils/BuildUtils';
import { DrawSize } from "@/mota/data/MapDataUtils";
import { ImageInfo, ImageName, imageSplit } from '@/mota/data/ImageLoader';
import Blockutils from '@/utils/BlockUtils';

export default class BuildAppend extends ScrollTool<ImageInfo> implements MotaInterface {

	public build: BuildUtils;

	public image: ImageName | undefined = undefined;

	public pos: DrawSize | undefined = undefined;

	public ZIndex: number = 6;

	public block: Blockutils = new Blockutils();

	public state: undefined | "appendSelect" | "appendStart" = undefined;

	public constructor(build: BuildUtils) {
		super({
			Left: 0,
			Top: 0,
			Width: 4,
			Height: 11,
			Padding: 0.15,
			ItemWidth: 1.2,
			ItemHeight: 1.5,
			ItemPadding: 0.1,
			List: <ImageInfo[]>imageSplit,
			ScrollWidth: 0.1,
		});
		this.build = build;
	}

	public get isOpen() {
		return this.block.IsBlockUp;
	}

	public Open(): Promise<void> {
		return this.block.Wait(async () => {
		}, () => {
			this.image = undefined;
			this.pos = undefined;
		});
	}

	public InView(): boolean {
		const { isOpen } = this;
		return isOpen;
	}

	public JudgeKey: MotaInterface["JudgeKey"] = (keyUtils): void => {
		if (!this.InView()) { return; }

		const { state, build, SelectItem } = this;

		for (const key of keyUtils.keyHistory) {
			if (key === "Escape") {
				if (state === undefined) {
					this.block.Release();
					keyUtils.delete(key);
				}
				else if (state === "appendSelect" || state === "appendStart") {
					this.image = undefined;
					this.pos = undefined;
					this.state = undefined;
					keyUtils.delete(key);
				}
			}
			if ((state === undefined)) {
				if (key === "ArrowUp") {
					this.SelectLastRow(true);
					keyUtils.delete(key);
				}
				else if (key === "ArrowDown") {
					this.SelectNextRow(true);
					keyUtils.delete(key);
				}
				else if (key === "ArrowLeft") {
					this.SelectLast(true);
					keyUtils.delete(key);
				}
				else if (key === "ArrowRight") {
					this.SelectNext(true);
					keyUtils.delete(key);
				}
				else if (key === "Enter" || key === " ") {
					if (SelectItem !== undefined) {
						this.handleSelect();
						keyUtils.delete(key);
					}
				}
			}
		}
	}

	public handleSelect(): void {
		const { build, SelectItem } = this;
		if (SelectItem !== undefined) {
			this.image = SelectItem[0];
			this.pos = undefined;
			this.state = "appendSelect";
		} else {
			this.state = undefined;
		}
	}

	public click: MotaInterface["click"] = ([], posf) => {
		if (!this.InView()) { return; }

		const { state, build } = this;
		const { range } = build;

		if ((state === undefined || state === "appendSelect") && range === "map") {
			const info = this.GetItemByPos(...posf);
			if (info !== undefined) {
				this.SelectItem = info;
				this.image = info[0];
				this.pos = undefined;
				this.state = "appendSelect";
			} else {
				this.state = undefined;
			}
		}
	}

	public mousedown: MotaInterface["mousedown"] = ([tx, ty]) => {
		if (!this.InView()) { return; }

		const { state, build, image } = this;
		const { range } = build;

		if (state === "appendSelect" && range === "draw" && image !== undefined) {
			this.pos = [tx - 4, ty, tx - 4, ty];
			this.state = "appendStart";
		}
	}


	public mousemove: MotaInterface["mousemove"] = ([tx, ty]) => {
		if (!this.InView()) { return; }

		const { state, build, pos } = this;
		const { range } = build;

		if (state === "appendSelect") {
			if (range === "draw") {
				this.pos = [tx - 4, ty];
			} else if (range === undefined) {
				this.pos = undefined;
			}
		}
		else if (state === "appendStart") {
			if (pos !== undefined) {
				const [x, y] = pos;
				let nx = tx - 4;
				let ny = ty;
				if (nx < x) { nx = x; }
				if (ny < y) { ny = y; }
				if (range === "draw") {
					this.pos = [x, y, nx, ny];
				} else if (range === undefined) {
					this.pos = [x, y];
				}
			}
		}
	}

	public mouseup: MotaInterface["mouseup"] = ([tx, ty]) => {
		if (!this.InView()) { return; }

		const { state, build, image, pos } = this;
		const { range } = build;

		if (state === "appendStart" && range === "draw") {
			if (pos !== undefined && image !== undefined) {
				const [x, y] = pos;
				let nx = tx - 4;
				let ny = ty;
				if (nx < x) { nx = x; }
				if (ny < y) { ny = y; }
				const size: DrawSize = (x === nx && y === ny) ? [x, y] : [x, y, nx, ny];
				build.AppendUnit([image, true, size, "run"])
			}
			this.state = undefined;
			this.image = undefined;
			this.pos = undefined;
		}
	}

	public mousewheel: MotaInterface["mousewheel"] = (delta: number) => {
		if (!this.InView()) { return; }

		const { state } = this;

		if (state === undefined) {
			const isDown = delta > 0;
			this.Progress += isDown ? 1 : -1;
		}
	}

	public Draw: MotaInterface["Draw"] = (draw) => {
		if (!this.InView()) { return; }

		const { _2d } = draw;
		const { state } = this;
		if (state !== undefined) { return; }

		_2d.save();

		_2d.fillStyle = "#FFFFFF";
		draw.SetFont(400, 1 / 4, "Mota");
		_2d.textAlign = "center";
		_2d.textBaseline = "top";
		_2d.strokeStyle = "#00FF00";
		draw.SetLineWidth(1 / 16);

		_2d.save();
		for (const [[image], isSelect, [x, y, w,], [bx, by, bw, bh]] of this.GetItemsSize()) {
			draw.DrawUnti([image, true, [x, y], "run"]);
			draw.fillText(image, x + w / 2, y + w + 0.05);
			if (isSelect) {
				draw.strokeRect(bx, by, bw, bh);
			}
		}
		_2d.restore();

		{
			const scrollSize = this.GetScrollSize();
			if (scrollSize) {
				const [[x, y, w, h], [sx, sy, sw, sh]] = scrollSize;
				_2d.fillStyle = "#00000044";
				draw.fillRect(x - 0.05, y - 0.05, w, h);
				_2d.fillStyle = "#000";
				draw.fillRect(sx - 0.05, sy - 0.05, sw, sh);
			}
		}

		_2d.restore();
	}

}
